package com.myzhouye.biz.controller;/***
 *                    _ooOoo_
 *                   o8888888o
 *                   88" . "88
 *                   (| -_- |)
 *                    O\ = /O
 *                ____/`---'\____
 *              .   ' \\| |// `.
 *               / \\||| : |||// \
 *             / _||||| -:- |||||- \
 *               | | \\\ - /// | |
 *             | \_| ''\---/'' | |
 *              \ .-\__ `-` ___/-. /
 *           ___`. .' /--.--\ `. . __
 *        ."" '< `.___\_<|>_/___.' >'"".
 *       | | : `- \`.;`\ _ /`;.`/ - ` : | |
 *         \ \ `-. \_ __\ /__ _/ .-` / /
 * ======`-.____`-.___\_____/___.-`____.-'======
 *                    `=---='
 *
 * .............................................
 *          佛祖保佑             永无BUG
 */

import com.myzhouye.biz.dto.BaseFactory;
import com.myzhouye.biz.dto.BaseFactoryMsgDTO;
import com.myzhouye.biz.security.RedisTokenUtils;
import com.myzhouye.biz.service.BaseFactoryService;
import com.myzhouye.biz.service.WarehouseService;
import com.myzhouye.biz.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.List;
import java.util.Map;

/**
 * @program: demo1
 * @description:
 * @author: 那条蠢鱼
 * @create: 2025-09-29 09:36
 **/
@RestController
@RequestMapping("view")
@Tag(name = "消息监听")
@RequiredArgsConstructor
@Slf4j
public class ViewController {

    private final BaseFactoryService baseFactoryService;
    private final WarehouseService warehouseService;
    private final RedisTokenUtils tokenUtils;

    /**
     * 消息监听，返回sse消息
     */
    @GetMapping(value = "factoryList",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(summary = "工厂情况")
    public Flux factoryList(@RequestHeader("Authorization") String token) {
        String actualToken = token.replace("Bearer ", "");
        return Flux.interval(Duration.ofSeconds(1))
                .flatMap(i -> tokenUtils.getLoginUser(actualToken)
                        // Token有效：返回工厂数据（封装为数据事件）
                        .flatMap(loginUser -> SecurityUtils.getCurrentUserId()
                                .map(userId -> {
                                    Map<String, BaseFactory> userFactoryMap = baseFactoryService.getUserFactories().get(userId);
                                    List<BaseFactoryMsgDTO> factories = userFactoryMap != null ? userFactoryMap.values().stream()
                                            .map(factory -> new BaseFactoryMsgDTO(
                                                    factory.getId(),
                                                    factory.getName(),
                                                    factory.getWarehouseSize(),
                                                    factory.getProductName(),
                                                    factory.getProductNums(),
                                                    factory.getUserId(),
                                                    factory.getProgress()
                                            )).toList() : List.of();
                                    // 数据事件格式：{type: "data", content: 实际数据}
                                    return Map.of("type", "data", "content", factories);
                                })
                        )
                        // Token无效：返回错误消息（封装为错误事件）
                        .switchIfEmpty(Mono.just(Map.of(
                                "type", "error",
                                "content", "Token已失效，连接终止"
                        )))
                )
                // 关键：发送错误事件后立即终止流（避免前端超时）
                .takeUntil(event -> "error".equals(((Map<String, Object>) event).get("type")))
                .doFinally(signalType -> log.info("客户端离开，消息链接关闭"));
    }

    @GetMapping(value = "warehouse",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(summary = "仓库详情")
    public Flux warehouse() {
        return Flux.interval(Duration.ofSeconds(1))
                .map(i -> warehouseService.getWarehouse())
                .doFinally(signalType -> log.info("客户端离开，消息链接关闭"));
    }


}
